/*

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; version 2
 of the License.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

#import <CoreSurface/CoreSurface.h>
#import <GraphicsServices/GraphicsServices.h>
#import "ScreenView.h"

// For device orientation, directions returned by the callback
  enum{
    kFACEUP = 0,
    kNORMAL = 1,
    kUPSIDEDOWN = 2,
    kLANDL = 3,
    kLANDR = 4,
    kFACEDOWN = 6
  };

static ScreenView *sharedInstance = nil;
void updateScreen() {
	[sharedInstance performSelectorOnMainThread:@selector(updateScreen) withObject:nil waitUntilDone: NO];
}
int getNextEvent(event_t *event) {
       return [sharedInstance getNextEvent:event];
}


@interface DoomEvent : NSObject {
  event_t ev;
}
- (id)initWithKeyDown:(int)button;
- (id)initWithKeyUp:(int)button;
- (id)initWithMouseX:(int)x Y:(int)y;
- (event_t)event;
@end

@implementation DoomEvent
- (id)initWithKeyDown:(int)button {
  self = [super init];
  if (self) {
    ev.type = ev_keydown;
    ev.data1 = button;
  }
  return self;
}

- (id)initWithKeyUp:(int)button {
  self = [super init];
  if (self) {
    ev.type = ev_keyup;
    ev.data1 = button;
  }
  return self;
}

- (id)initWithMouseX:(int)x Y:(int)y {
  self = [super init];
  if (self) {
    ev.type = ev_mouse;
    ev.data2 = x;
    ev.data3 = y;
  }
  return self;
}

- (event_t)event {
  return ev;
}
@end

@implementation ScreenView 


- (void)deviceOrientatSionChanged:(int)screenOrientation
{
 if(currOrient == screenOrientation)
    return;
 // How long will the main view rotation take? (seconds)
  float rotDur = .5;
  // Target rotation position in degrees
  int targetRot;


  // set the orientation based on the event from UIHardware
  switch(screenOrientation) 
    {
    case kFACEUP:
    case kFACEDOWN:
      targetRot = currRot;
      break;
    case kNORMAL:
      targetRot = 0;
      break;
    case kLANDL:
      targetRot = 90;
      break;
    case kUPSIDEDOWN:
      targetRot = 180;
      break;
    case kLANDR:
      targetRot = 270;
      break;
    }
	
	if(targetRot != currRot)
    {
      // setup an animation for rotation, anything between the 
      // beginAnimations, endAnimations block is animated
      [UIView beginAnimations:nil];
      [UIView setAnimationDuration:rotDur];
      [self setRotationBy: targetRot-currRot];
	  [self setBounds:CGRectMake(0,0,[self bounds].size.width,[self bounds].size.height)];
//	  [self setOrigin:CGPointMake(0,-120)];


/*	  for (id view in [self subviews])
	  {
	  
		  if ([[view class] isEqual:[ScreenView class]])
		  {
			  if(targetRot != 0 && targetRot != 180 )
			  {
				[view setBounds:CGRectMake(0,0,[self frame].size.width+20,[view frame].size.height)];
				[view setOrigin:CGPointMake(-90,90)];
			  }
			  else
			  {
				  [view setOrigin:CGPointMake(0,0)];

			  }
		  }
		  */
	  }
     [UIView endAnimations];

      currRot = targetRot;
    

  currOrient = screenOrientation;

}


- (id)initWithFrame:(CGRect)frame {
	if ((self == [super initWithFrame:frame])!=nil) {
            sharedInstance = self;
            initGraphics = 0;
			eventQueue = [[NSMutableArray alloc] init];
			//[UIHardware deviceOrientation: TRUE];
			
	}
	return self;
}

- (void)updateScreen {

	[sharedInstance setNeedsDisplay];
}

- (void)dealloc {
        [ screenLayer release ];
        pthread_mutex_destroy(&screenUpdateMutex);
        pthread_cond_destroy(&screenUpdateLock);
	[super dealloc];
}

-(void)setButtonEnter:(UIPushButton *)v
{
	buttonEnter = v;

	[self addSubview:buttonEnter];
	[buttonEnter addTarget:self action:@selector(sendDoomKeyEnter) forEvents:1];

}

- (void)drawRect:(CGRect)rect{
    if (initGraphics == 0) {
        int i;
        CFMutableDictionaryRef dict;
        int w = 320;
        int h = 240;

        int pitch = w * 2, allocSize = 2 * w * h;
        char *pixelFormat = "565L";

        initGraphics = 1;
        pthread_cond_init(&screenUpdateLock, NULL);
        pthread_mutex_init(&screenUpdateMutex, NULL);

        dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
            &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

        CFDictionarySetValue(dict, kCoreSurfaceBufferGlobal, kCFBooleanTrue);
        CFDictionarySetValue(dict, kCoreSurfaceBufferMemoryRegion, CFSTR("PurpleGFXMem"));
        CFDictionarySetValue(dict, kCoreSurfaceBufferPitch, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pitch));
        CFDictionarySetValue(dict, kCoreSurfaceBufferWidth, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &w));
        CFDictionarySetValue(dict, kCoreSurfaceBufferHeight, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &h));
        CFDictionarySetValue(dict, kCoreSurfaceBufferPixelFormat, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, pixelFormat));
        CFDictionarySetValue(dict, kCoreSurfaceBufferAllocSize, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &allocSize));

        screenSurface = CoreSurfaceBufferCreate(dict);
        CoreSurfaceBufferLock(screenSurface, 3);

        screenLayer = [[LKLayer layer] retain];
      //  [screenLayer setFrame: CGRectMake(-64.0f, 100.0f, 427, 320)];
        [screenLayer setFrame: CGRectMake((440/2)-(400/2), 20.0f, 400, 300)];

        [screenLayer setContents: screenSurface];
        [screenLayer setOpaque: YES];
        [[self _layer] addSublayer: screenLayer];

        CoreSurfaceBufferUnlock(screenSurface);
    }
}


- (void)mouseDown:(GSEvent*)event {
  int key = 0;

  // click count seems to always be 1, so this is not useful
  //int cc = GSEventGetClickCount(event);
  //NSLog(@"mouseDown with click count %d", cc);

  CGPoint r = GSEventGetLocationInWindow(event);
  lastMousePos = r;
  
    CGRect fb = CGRectMake(-80.0f, 0.0f, 480.0f, 80.0f);
	
	CGRect lr = CGRectMake(0.0f, 0.0f, 80.0f, 480.0f);

	
	if (CGRectContainsPoint(fb,r)) // Forward/backward - ie ignore click
	{
		return;
	}
	else if (CGRectContainsPoint(lr,r)) // Forward/backward - ie ignore click
	{
		return;
	}

  if (GSEventIsChordingHandEvent(event)) {
    key = KEY_RCTRL;
  }else{
    if (lastMousePos.x < 240) {
      key = KEY_ENTER;
    }else{
      key = ' ';
    }
  }
    
  if (key) {
    [eventQueue addObject:[[DoomEvent alloc] initWithKeyDown:key]];
    lastKey = key;
  }
}


- (void)mouseDragged:(GSEvent*)event 
{

  CGPoint r = GSEventGetLocationInWindow(event);
  CGRect fb = CGRectMake(-80.0f, 0.0f, 480.0f, 80.0f);
	CGRect lr = CGRectMake(0.0f, 0.0f, 80.0f, 480.0f);
	
	int y;
	int x;
    
  if (CGRectContainsPoint(fb,r)) // Forward/backward
  {
   y = (int)(r.x - lastMousePos.x) << 4;
   x = 0;
  }
  else if (CGRectContainsPoint(lr,r))
  {
	x =  (int)(r.y - lastMousePos.y) << 4;
	y = 0;
  }
  else
  return;
  
 
  [eventQueue addObject:[[DoomEvent alloc] initWithMouseX:x Y:y]];
  lastMousePos = r;
}


- (void)mouseUp:(GSEvent*)event {
  if (lastKey) {
    [eventQueue addObject:[[DoomEvent alloc] initWithKeyUp:lastKey]];
    lastKey = 0;
  }
}

- (int)getNextEvent:(event_t*)event {
  if ([eventQueue count] == 0) return 0;
  
  DoomEvent* doomEvent = [eventQueue objectAtIndex:0];
  [eventQueue removeObjectAtIndex:0];
  
  *event = [doomEvent event];
  if (event->type != ev_mouse)
    NSLog(@"event %d %d %d %d",
       event->type, event->data1, event->data2, event->data3);
  
  return 1;
}

@end
